package top.heue.utils.container

import android.content.Context
import android.content.Intent
import kotlinx.coroutines.*
import top.heue.utils.lifecycle.helper.onMain
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger

/**
 * FragmentContainer
 * .with(fragment)
 * .title(title)
 * .tag(tag)
 * .container(container)
 * .callback(callback)
 * .newTask(true)
 * fitsSystemWindows(true)
 * .start(this)
 */
object FragmentContainer {
    const val TAG_ID = "id"

    private var defaultContainer: Class<*> = ContainActivity::class.java
    private var defaultCallback: Class<out ContainCallback>? = null

    private val configMap: ConcurrentHashMap<Int, ContainConfig> by lazy { ConcurrentHashMap() }
    private val jobMap: ConcurrentHashMap<Int, Job> by lazy { ConcurrentHashMap() }
    private val dispatcher by lazy { CoroutineScope(Dispatchers.IO) }

    private val idGen = AtomicInteger(0)

    /** 打开页面*/
    fun startFragment(
        context: Context,
        fragmentClass: Class<*>,
        vararg params: Any,
        initializer: (ContainConfig.() -> Unit)? = null
    ) = onMain {
        val config = ContainConfig(
            idGen.incrementAndGet(),
            container = defaultContainer,
            fragmentClass = fragmentClass,
            callbackClass = defaultCallback,
            params = params.toList()
        )
        if (initializer != null) {
            initializer(config)
        }
        configMap[config.id] = config
        val i = config.intent?.apply {
            setClass(context, config.container)
        } ?: Intent(context, config.container)
        if (config.isNewTask) {
            i.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        i.putExtra(TAG_ID, config.id)
        context.startActivity(i)
    }

    fun container(container: Class<*>) = apply {
        defaultContainer = container
    }

    fun callback(callback: Class<out ContainCallback>) = apply {
        defaultCallback = callback
    }

    /** 获取对应id的启动配置，并查找如果该id在销毁中的话就取消销毁*/
    fun config(id: Int?): ContainConfig? {
        if (id == null) return null
        if (jobMap[id] != null) jobMap[id]!!.cancel()
        return configMap[id]
    }

    /** 延迟1.5秒后销毁该页面*/
    fun destroy(id: Int) {
        val job = dispatcher.launch {
            delay(1500)
            configMap.remove(id)
        }
        job.invokeOnCompletion {
            jobMap.remove(id)
        }
        jobMap[id] = job
    }
}